﻿namespace com.game.module.fight.arpg
{
    using com.game.basic;
    using com.game.data;
    using com.game.manager;
    using com.game.utils;
    using com.game.vo;
    using System;
    using System.Runtime.InteropServices;
    using UnityEngine;

    public sealed class GameFormula
    {
        public static void CalcDamage(SysSkillBaseVo skillVo, float baseAttck, out uint crit)
        {
            float num;
            if (skillVo.att_type == 1)
            {
                num = 1.15f;
            }
            else
            {
                num = 1.15f;
            }
            num = (((num * skillVo.data_per) / 10000f) * baseAttck) + skillVo.data_fixed;
            crit = (uint) num;
        }

        public static void CalcDamage(BaseRoleVo aer, BaseRoleVo der, SysSkillBaseVo skillVo, out int damageVal, out uint damageType, out uint stateType)
        {
            CalcDamage(aer, der, skillVo, 1, out damageVal, out damageType, out stateType);
            uint damageBack = 0;
            CalcDamageBack(der, skillVo, damageVal, out damageBack);
            uint damageVam = 0;
            CalcVam(aer, der, skillVo, damageVal, out damageVam);
        }

        public static void CalcDamage(BaseRoleVo aer, BaseRoleVo der, SysSkillBaseVo skillVo, uint targetNum, out int damageVal, out uint damageType, out uint stateType)
        {
            int type = der.Type;
            if (der.stateInfo.IsInState(StateVo.CANT_BEAT))
            {
                damageVal = 0;
                damageType = 3;
                stateType = 0;
            }
            else
            {
                uint num2;
                uint num3;
                CalcHitCrit(aer, der, out num2, out num3);
                damageType = CalcDamageType(num2, num3);
                double num4 = 0.0;
                switch (damageType)
                {
                    case 0:
                        num4 = 0.0;
                        break;

                    case 2:
                        num4 = CalcDamageInternal(aer, der, skillVo) * (1.5f + (aer.CritAdd * aer.fightAttVo.CritAddRate));
                        break;

                    case 3:
                        num4 = CalcDamageInternal(aer, der, skillVo);
                        break;
                }
                stateType = CalcDamageStateType(aer, der, skillVo);
                int num5 = 0;
                if (der.job == skillVo.restricted_job_id)
                {
                    num5 = Mathf.Max(skillVo.restricted_factor / 0x2710, 1);
                }
                else
                {
                    num5 = 1;
                }
                double a = Math.Max((double) (num4 * num5), (double) 1.0) * (1.0 + (MathUtils.Random(-10000, 0x2710) * 1E-06));
                double num7 = Math.Round(a);
                damageVal = Convert.ToInt32(num7);
            }
        }

        private static void CalcDamageBack(BaseRoleVo der, SysSkillBaseVo skillVo, int damage, out uint damageBack)
        {
            if (skillVo.att_type == 1)
            {
                damageBack = Convert.ToUInt32(Math.Round((double) (damage * (der.DmgBackP * der.fightAttVo.DmgBackPRate))));
            }
            else if (skillVo.att_type == 2)
            {
                damageBack = Convert.ToUInt32(Math.Round((double) (damage * (der.DmgBackM * der.fightAttVo.DmgBackMRate))));
            }
            else
            {
                damageBack = 0;
            }
        }

        private static double CalcDamageInternal(BaseRoleVo aer, BaseRoleVo der, SysSkillBaseVo skillVo)
        {
            int type = aer.Type;
            int num2 = der.Type;
            double num3 = 0.0;
            num3 = GetSkillDmg(aer, der, skillVo) + Mathf.Max((float) ((aer.AbHurt + aer.fightAttVo.AbHurt) - der.AbDef), 0f);
            if (skillVo.position == 0)
            {
                num3 *= 1f + (aer.AtkNormalAdd * aer.fightAttVo.AtkNormalAddRate);
            }
            return Math.Max(1.0, num3);
        }

        private static uint CalcDamageStateType(BaseRoleVo aer, BaseRoleVo der, SysSkillBaseVo skillVo)
        {
            switch (der.Type)
            {
                case 400:
                {
                    MonsterVo vo = der as MonsterVo;
                    if (((skillVo.knock_down_factor - vo.MonsterVO.anti_knock_down) > 0) && (MathUtils.Random() < skillVo.knock_down_opp))
                    {
                        return 2;
                    }
                    if (((skillVo.knock_back_factor - vo.MonsterVO.anti_knock_back) > 0) && (MathUtils.Random() < skillVo.knock_back_opp))
                    {
                        return 3;
                    }
                    return 0;
                }
                case 100:
                    if ((skillVo.is_knock_down_for_player && ((skillVo.knock_down_factor - der.AntiKnockDown) > 0L)) && (MathUtils.Random() < skillVo.knock_down_opp))
                    {
                        return 2;
                    }
                    if ((skillVo.is_knock_back_for_player && ((skillVo.knock_back_factor - der.AntiKnockBack) > 0L)) && (MathUtils.Random() < skillVo.knock_back_opp))
                    {
                        return 3;
                    }
                    break;
            }
            return 0;
        }

        private static uint CalcDamageType(uint aerDodge, uint aerCrit)
        {
            if (MathUtils.Random() <= aerDodge)
            {
                return 0;
            }
            return ((MathUtils.Random() > aerCrit) ? 3 : 2);
        }

        public static double CalcGeneralFightPoint(AttributeInfo attr)
        {
            return Math.Round((double) (((((((((((attr.hpFull * 0.4) + (attr.attP * 3)) + (attr.attM * 3)) + (attr.defP * 0.75)) + (attr.defM * 0.75)) + (attr.hit * 10)) + (attr.dodge * 15)) + (attr.crit * 15)) + (attr.flex * 10)) + (attr.abHurt * 1.25)) + (attr.abDef * 1.25)));
        }

        private static void CalcHitCrit(BaseRoleVo aer, BaseRoleVo der, out uint dodge, out uint crit)
        {
            int type = aer.Type;
            float hit = aer.Hit;
            float num3 = aer.Crit;
            uint level = (uint) aer.Level;
            int num5 = der.Type;
            float num6 = der.Dodge;
            float flex = der.Flex;
            uint num8 = (uint) der.Level;
            float num9 = 0f + (((num6 * der.fightAttVo.DodgeRate) * (1f - hit)) * aer.fightAttVo.HitRate);
            dodge = (uint) Math.Round((double) (Math.Max(num9, 0f) * 10000.0));
            float num10 = 0.1f + (((num3 * aer.fightAttVo.CritRate) * (1f - der.Flex)) * der.fightAttVo.FlexRate);
            crit = (uint) Math.Round((double) (Math.Max(Math.Min(num10, 1f), 0.1f) * 10000.0));
        }

        public static void CalcRecoverHp(BaseRoleVo aer, BaseRoleVo der, SysSkillBaseVo skillVo, out uint recoverHp)
        {
            recoverHp = Convert.ToUInt32(Math.Round(GetSkillDmg(aer, der, skillVo)));
        }

        private static void CalcVam(BaseRoleVo aer, BaseRoleVo der, SysSkillBaseVo skillVo, int damage, out uint damageVam)
        {
            damageVam = 0;
            if (damage > 0)
            {
                if (skillVo.att_type == 1)
                {
                    damageVam = Convert.ToUInt32(Math.Round((double) ((damage * aer.AttPVam) * aer.fightAttVo.AttPVamRate)));
                }
                else if (skillVo.att_type == 2)
                {
                    damageVam = Convert.ToUInt32(Math.Round((double) ((damage * aer.AttMVam) * aer.fightAttVo.AttMVamRate)));
                }
            }
        }

        private static double GetLvData(int lv)
        {
            return (double) (BaseDataMgr.instance.GetSysLogDataVo((uint) lv, 10).data * 1E-10f);
        }

        private static uint GetSeqAttDamage(BaseRoleVo aer, uint aerAtt)
        {
            if (aer.Type == 100)
            {
                PlayerVo vo = aer as PlayerVo;
                return (uint) (aerAtt * (1f + (vo.SeqAttack * 0.05f)));
            }
            return aerAtt;
        }

        private static double GetSkillDmg(BaseRoleVo aer, BaseRoleVo der, SysSkillBaseVo skillVo)
        {
            int num = skillVo.att_type;
            double num2 = skillVo.data_per * 0.0001f;
            int num3 = skillVo.data_fixed;
            double num4 = 0.0;
            switch (num)
            {
                case 1:
                {
                    double num5 = aer.AttrPhy + aer.fightAttVo.AttrPhySum;
                    double num6 = (der.DefP + der.fightAttVo.DefPhySum) * (1f - (aer.AttPPen * (1f - der.DefPPen)));
                    num4 = (num5 * 0.15000000596046448) + (Math.Max((double) 0.0, (double) (num5 - num6)) * 1.0);
                    return (num3 + (num2 * num4));
                }
                case 2:
                {
                    double num7 = aer.AttrMag + aer.fightAttVo.AttrMagSum;
                    double num8 = (der.DefM + der.fightAttVo.DefMagSum) * (1f - (aer.AttMPen * (1f - der.DefMPen)));
                    num4 = (num7 * 0.15000000596046448) + (Math.Max((double) 0.0, (double) (num7 - num8)) * 1.0);
                    return (num3 + (num2 * num4));
                }
                case 3:
                {
                    double num9 = aer.AttrMag + aer.fightAttVo.AttrMagSum;
                    num4 = (num9 * 0.15000000596046448) + (aer.AttrMag * 1f);
                    return (num3 + (num2 * num4));
                }
            }
            return 0.0;
        }

        public static float PreCalcDamage(BaseRoleVo aer, BaseRoleVo der, SysSkillBaseVo skillVo)
        {
            int num;
            uint num2;
            uint num3;
            CalcDamage(aer, der, skillVo, out num, out num2, out num3);
            return (((float) num) / 1.01f);
        }
    }
}

